<?php

namespace app\common\model\virtual;


use app\common\loader\ModelMerchant;
use app\common\model\BaseModel;
use think\Exception;


/**
 * 虚码活动商品
 * Class VirtualPromoProduct
 * @package app\common\model
 */
class VirtualPromoProductModel extends BaseModel
{
    //
    protected $name = 'virtual_promo_product';

    // 设置字段信息
    protected $schema = [
        'id' => 'int',        // 序号
        'mer_id' => 'string',        //
        'vp_id' => 'int',        // 虚码规则ID
        'product_code' => 'string',        // 单商品ID,
        'num' => 'int',        // 商品数量,联合活动有效
        'op_user' => 'int',        // 操作人
        'create_at' => 'datetime',        // 创建时间
        'update_at' => 'datetime',        // 更新时间
    ];

    /**
     * 获取指定活动中特殊规则的数量
     * @param array $vpids 活动ID
     * @return array
     */
    public function getNums(array $vpids): array
    {
        return $this->db()->whereIn('vp_id', $vpids)->group('vp_id')->column('count(id)', 'vp_id');
    }


    /**
     * 验证提交活动商品数量
     * @param string $mer_id |商户ID
     * @param int    $vp_id |活动ID
     * @param array  $product_data |本次验证数据
     * @param int    $product_type | 活动类型
     * @param array  $union_option | 联合活动配置
     * @return array
     * @throws Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function validVirtualPromoProduct(string $mer_id, int $vp_id, array $product_data, int $product_type, array $union_option = []): array
    {

        // 联合活动时, 联合规格不能为空
        if ($product_type === 2 && empty($union_option)) {
            throw  new Exception('活动设置异常,请联系经销商.', API_ERROR);
        }
        // 1.获取活动的商品
        // 2.判断提交的商品是否全部在活动中
        // 3.根据类型判断是否达到要求
        $promo_product = $this->db()->where('mer_id', $mer_id)->where('vp_id', $vp_id)->column('num', 'product_code');

        if (empty($promo_product)) {
            throw  new Exception('提交的商品未在活动中,请联系经销商.', API_ERROR);
        }

        // 获取商品的名称
        $product_title = ModelMerchant::Product()->getProductTitle($mer_id, array_keys($promo_product));

        // 重新组织有效的商品
        $valid_product = [];
        foreach ($product_data as $row) {
            if (isset($promo_product[$row['code']])) {
                $row['product_title'] = $product_title[$row['code']];
                $valid_product[$row['code']] = $row;
            }
        }
        if (empty($valid_product)) {
            throw  new Exception('提交商品不符合活动要求,请重新扫商品码.', API_ERROR);
        }

        // 提交的数量大于 活动数量时,等于活动数量
        // 单商品活动,只能有一个有效的商品
        if ($product_type === 1) {
            if (count($valid_product) > 1) {
                throw  new Exception('提交的数据异常,请联系开发商.', API_ERROR);
            }
            // 纠正 提交的商品数量
            foreach ($valid_product as $k => $row) {
                // 提交的数量大于 活动数量时,等于活动数量
                if ($row['num'] > $promo_product[$row['code']]) {
                    $valid_product[$k]['num'] = $promo_product[$row['code']];
                }
            }
        }

        // 验证联合活动
        if (!empty($union_option)) {
            // 联合规则   { sum: 0 ->保计满足数据,rule=2 有效, rule:-> 1: 商品满足 2,数量满足}

            // 满足商品
            if ($union_option['rule'] === 1) {
                // 验证活动商品是否满足条件

                $error_product = [];
                foreach ($promo_product as $code => $num) {
                    if (!isset($row)) {
                        $error_product[] = sprintf("%s|%s 未扫码", $code, $product_title[$code] ?? '');
                        continue;
                    }
                    if ($num > $valid_product[$code]['num']) {
                        $error_product[] = sprintf("%s|%s 数量不足", $code, $product_title[$code] ?? '');
                        continue;
                    }
                    // 提交的数量大于 活动数量时,等于活动数量
                    if ($valid_product[$code]['num'] > $num) {
                        $valid_product[$code]['num'] = $num;
                    }

                }
                if (!empty($error_product)) {
                    throw new Exception(implode(',', $error_product), API_ERROR);
                }
            }

            // 满足数量
            if ($union_option['rule'] === 2) {
                $sum_num = array_sum(array_column($valid_product, 'num'));
                if ($sum_num < $union_option['sum']) {
                    throw  new Exception('提交商品数量不符合活动要求,请继续扫商品码.', API_ERROR);
                }
            }
        }

        return array_values($valid_product);

    }
}
